package com.bidevalution.business.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.bidevalution.dao.entity.BeEvalutionColumn;
import com.bidevalution.dao.entity.BeEvalutionExpert;
import com.bidevalution.dao.entity.BeEvalutionOutcome;
import com.bidevalution.dao.entity.BeSectionEnterprise;
import com.bidevalution.dao.mapper.BeEvalutionOutcomeMapper;
import com.bidevalution.dao.mapper.BeSectionEnterpriseMapper;
import com.bidevalution.dao.mapper.BeSectionExpertProgressMapper;
import com.bidevalution.dao.mapper.BeSectionStepMapper;
import com.bidevalution.support.context.Constant;
import com.bidevalution.support.context.Constants;
import com.bidevalution.support.util.LogUtil;
import com.bidevalution.support.util.MapUtil;
import com.bidevalution.support.util.RedisLockTool;
import com.bidevalution.support.util.StringUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qtp.core.redis.RedisUtil;
import com.qtp.core.util.OConvertUtils;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bidevalution.business.context.StepStage;
import com.bidevalution.business.service.BeEvalutionOutcomeService;
import com.bidevalution.business.service.BeSectionExpertInfoService;
import com.bidevalution.business.service.BeSectionExpertProgressService;
import com.bidevalution.business.service.BeSectionStepJobService;
import com.bidevalution.business.service.BeSectionStepService;
import com.bidevalution.dao.entity.BeSectionExpertInfo;
import com.bidevalution.dao.entity.BeSectionExpertProgress;
import com.bidevalution.dao.entity.BeSectionStep;
import com.bidevalution.dao.jdbc.JdbcTemplateSupport;
import com.bidevalution.service.layout.ColumnHeader;
import com.bidevalution.service.layout.ColumnHeader.ColumnType;
import com.bidevalution.support.context.ResponseObject;
import com.bidevalution.support.context.WebSocketOpTypeEnum;
import com.bidevalution.support.factory.WebSocketService;
import com.bidevalution.support.websocket.WebSocketCached;
import com.qtp.core.util.IdsUtil;
import org.springframework.util.StringUtils;

@Service
public class BeEvalutionOutcomeServiceImpl implements BeEvalutionOutcomeService {
	@Autowired
	private JdbcTemplateSupport jdbcTemplateSupport;
	@Autowired
	private BeSectionExpertInfoService beSectionExpertInfoService;
	@Autowired
	private BeEvalutionOutcomeMapper beEvalutionOutcomeMapper;
	@Autowired
	private WebSocketService webSocketService;
	@Autowired
	private BeSectionExpertProgressService beSectionExpertProgressService;
	@Autowired
	private BeSectionStepMapper beSectionStepMapper;
	@Autowired
	private BeSectionEnterpriseMapper beSectionEnterpriseMapper;
	@Autowired
	private BeSectionExpertProgressMapper beSectionExpertProgressMapper;
	@Autowired
	private BeSectionStepJobService beSectionStepJobService;
	private Logger logger = Logger.getLogger(getClass());
	/**
	 * 所有专家都提交完成的任务锁标识
	 */
	private static String AFTER_EXECUTE_JOB_LOCK = "AFTER_EXECUTE_JOB_LOCK";
	@Override
	@Transactional
	public void save(List<Map<String, Object>> dataList, List<ColumnHeader> columnHeaderList,
			BeSectionStep beSectionStep, String expertId, String layoutCode, String submitCode, String isFinish,
			List<BeEvalutionColumn> evalutionColumnList) throws Exception {
		logger.info(beSectionStep.getStepName() + ",保存结果.>>>>>>>>>>>>>" + dataList);
		StringBuilder sqlBuilder;
		Map<String, Object> uniqueMap = Maps.newHashMap();
		List<String> columnCodeList = Lists.newArrayList();
		for (BeEvalutionColumn beEvalutionColumn : evalutionColumnList) {
			columnCodeList.add(beEvalutionColumn.getColumnCode().toLowerCase());
		}
		for (Map<String, Object> dataMap : dataList) {
			dataMap.put("sectionStepId", beSectionStep.getSeqId());
			dataMap.put("expertId", expertId);
			dataMap.put("layoutCode", layoutCode);
			dataMap.put("submitCode", submitCode);
			dataMap.put("sectionStepCode", beSectionStep.getStepCode());
			dataMap.put("sectionId", beSectionStep.getSectionId());
			dataMap.put("isDel", "0");
			dataMap.put("isFinish", isFinish);
			if (StringUtils.isEmpty(dataMap.get("enterprise_id"))) {
				dataMap.put("enterprise_id", "0");
			}
			if (dataMap.get("seqId") == null) {
				RowMapper<BeEvalutionOutcome> rm = BeanPropertyRowMapper.newInstance(BeEvalutionOutcome.class);
				BeEvalutionOutcome beEvalutionOutcome = jdbcTemplateSupport.selectForObject(
						"select seq_id from be_evalution_outcome where section_id=:sectionId and section_step_id=:sectionStepId and expert_id=:expertId and enterprise_id=:enterpriseId and layout_code=:layoutCode and is_del=:isDel limit 1",
						MapUtil.create().putValue("sectionId", beSectionStep.getSectionId())
								.putValue("sectionStepId", beSectionStep.getSeqId()).putValue("expertId", expertId)
								.putValue("enterpriseId", dataMap.get("enterprise_id"))
								.putValue("layoutCode", layoutCode).putValue("isDel", Constants.ZERO).getMap(),
						rm);
				if (beEvalutionOutcome != null) {
					uniqueMap.put("seqId", beEvalutionOutcome.getSeqId());
				}
			} else {
				RowMapper<BeEvalutionOutcome> rm = BeanPropertyRowMapper.newInstance(BeEvalutionOutcome.class);
				BeEvalutionOutcome beEvalutionOutcome = jdbcTemplateSupport.selectForObject(
						"select seq_id from be_evalution_outcome where seq_id=:seqId",
						MapUtil.create().putValue("seqId", dataMap.get("seqId")).getMap(), rm);
				if (beEvalutionOutcome != null) {
					uniqueMap.put("seqId", beEvalutionOutcome.getSeqId());
				}
			}
			if (uniqueMap.isEmpty()) {
				sqlBuilder = new StringBuilder("insert into be_evalution_outcome(");
				sqlBuilder.append("seq_id").append(",").append("section_step_id").append(",").append("expert_id")
						.append(",").append("layout_code").append(",").append("submit_code").append(",")
						.append("section_step_code").append(",").append("section_id").append(",").append("is_del")
						.append(",").append("unpassed_reason").append(",").append("is_finish").append(",");
				;
				for (ColumnHeader columnHeader : columnHeaderList) {
					if (columnCodeList.contains(columnHeader.getCode().toLowerCase())) {
						sqlBuilder.append(columnHeader.getCode().toLowerCase()).append(",");
					}
				}
				sqlBuilder.append("create_time").append(",").append("update_time").append(")values(").append("'")
						.append(dataMap.get("seqId") == null ? IdsUtil.uuid() : dataMap.get("seqId")).append("',")
						.append(":sectionStepId").append(",").append(":expertId").append(",").append(":layoutCode")
						.append(",").append(":submitCode").append(",").append(":sectionStepCode").append(",")
						.append(":sectionId").append(",").append(":isDel").append(",").append(":unpassedReason")
						.append(",").append(":isFinish").append(",");
				for (ColumnHeader columnHeader : columnHeaderList) {
					if (columnCodeList.contains(columnHeader.getCode().toLowerCase())) {
						sqlBuilder.append(":").append(columnHeader.getCode()).append(",");
					}
				}
				sqlBuilder.append("now()").append(",").append("now()").append(")");

				dataMap.put("unpassedReason", getUnpassedReason(beSectionStep, columnHeaderList, dataMap));
				//行计算
//				beSectionStepJobService.callRowJob(beSectionStep.getSeqId(), submitCode,expertId,layoutCode,StepStage.Between,uniqueMap);
//				
				jdbcTemplateSupport.insert(sqlBuilder.toString(), dataMap);
			} else {
				sqlBuilder = new StringBuilder("update be_evalution_outcome set ");
				for (ColumnHeader columnHeader : columnHeaderList) {
					if (columnCodeList.contains(columnHeader.getCode().toLowerCase())) {
						sqlBuilder.append(
								columnHeader.getCode().toLowerCase() + "=:" + columnHeader.getCode().toLowerCase())
								.append(",");
					}
				}
				sqlBuilder.append("unpassed_reason=:unpassedReason").append(",");
				sqlBuilder.append("update_time=:updateTime").append(",").append("is_finish=:isFinish").append(" where seq_id=:seqId");
				for (ColumnHeader columnHeader : columnHeaderList) {
					for (Entry<String, Object> entry : dataMap.entrySet()) {
						if (entry.getKey().toLowerCase().equals(columnHeader.getCode().toLowerCase())
								&& columnCodeList.contains(columnHeader.getCode().toLowerCase())) {
							uniqueMap.put(entry.getKey().toLowerCase(), entry.getValue());
							break;
						}
					}
				}
				uniqueMap.put("updateTime", new Date());
				uniqueMap.put("isFinish", isFinish);
				uniqueMap.put("unpassedReason", getUnpassedReason(beSectionStep, columnHeaderList, dataMap));
				//行计算
//				beSectionStepJobService.callRowJob(beSectionStep.getSeqId(), submitCode,expertId,layoutCode,StepStage.Between,uniqueMap);				
				jdbcTemplateSupport.update(sqlBuilder.toString(), uniqueMap);
			}
		}

		/**************评审过程中调用事件***************************/
		//先执行环节关联的所有子节点的提前计算任务
		beSectionStepJobService.callStepUnionJob(beSectionStep, submitCode,
				expertId, layoutCode, StepStage.Between);
		//在执行当前环节任务
		beSectionStepJobService.callStepJob(beSectionStep, submitCode, StepStage.Between, expertId, layoutCode);

		// 通知其他人员
		if ("1".equals(isFinish)) {
			//执行该环节所有专家完成之后的事件
			beSectionStepJobService.callStepUnionJob(beSectionStep, submitCode,
					expertId, layoutCode, StepStage.submit);
			beSectionStepJobService.callStepJob(beSectionStep, submitCode, StepStage.submit, expertId, layoutCode);
//			try {
			//加锁
				/*boolean lock = RedisLockTool.getDistributedLock(RedisUtil.getJedis(), AFTER_EXECUTE_JOB_LOCK + beSectionStep.getSeqId(), beSectionStep.getSeqId(), 60 * 5);
				if (lock) {*/

			//其他专家都已经提交完成
			if (beSectionExpertProgressService.isOtherExpertFinished(beSectionStep.getSeqId(), expertId)) {
				logger.info("其他专家都已经提交完成，开始执行job任务，标段id[" + beSectionStep.getSectionId() + "]，环节id[" + beSectionStep.getSeqId() + "],专家id[" + expertId + "]");
				//执行该环节所有专家完成之后的事件
				beSectionStepJobService.callStepUnionJob(beSectionStep, submitCode,
						expertId, layoutCode, StepStage.After);
				beSectionStepJobService.callStepJob(beSectionStep, submitCode, StepStage.After, expertId, layoutCode);
				logger.info("所有专家提交之后的job任务执行完成。。。");
			} else {
				logger.info("其他专家未提交完成，不执行job任务，标段id[" + beSectionStep.getSectionId() + "]，环节id[" + beSectionStep.getSeqId() + "],专家id[" + expertId + "]");
			}
			//更新当前所有子节点环节完成状态
			BeSectionExpertProgress beSectionExpertProgress = beSectionExpertProgressService
					.selectByKey(beSectionStep.getSeqId(), expertId);
			beSectionExpertProgress.setIsFinish(isFinish);
			beSectionExpertProgressService.update(beSectionExpertProgress);
			for (BeSectionStep sectionStep : beSectionStepMapper.getAllChildSectionStep(beSectionStep.getSectionId(),
					beSectionStep.getStepCode())) {
				beSectionExpertProgress = beSectionExpertProgressService.selectByKey(sectionStep.getSeqId(), expertId);
				beSectionExpertProgress.setIsFinish(isFinish);
				beSectionExpertProgressService.update(beSectionExpertProgress);
			}
			//更新父环节完成状态
			updateParentFinishState(beSectionStep.getSectionId(), beSectionStep.getStepCode());

			// 一个专家完成提交，则通知其他专家
			for (BeSectionExpertInfo sectionExpertInfo : beSectionExpertInfoService
					.getAllListBySectionId(beSectionStep.getSectionId())) {
				logger.info(sectionExpertInfo.getSeqId() + ":" + beSectionStep.getStepCode() + ",发送websocket:"
						+ WebSocketCached.getExpertChannelContextMap().get(sectionExpertInfo.getSeqId()));
				// 发送websocket消息
				if (WebSocketCached.getExpertChannelContextMap().get(sectionExpertInfo.getSeqId()) != null) {
					webSocketService.send(
							WebSocketCached.getExpertChannelContextMap().get(sectionExpertInfo.getSeqId()),
							new ResponseObject(WebSocketOpTypeEnum.EXPERT_FINISH));
				}
			}

			/*} finally {
				//释放锁标识
				RedisLockTool.releaseDistributedLock(RedisUtil.getJedis(), AFTER_EXECUTE_JOB_LOCK + beSectionStep.getSeqId(), beSectionStep.getSeqId());
			}*/
		}
	}

	/**
	 * 更新父环节完成状态
	 * @param sectionId
	 * @param stepCode
	 * @throws Exception
	 */
	private void updateParentFinishState(String sectionId, String stepCode) throws Exception {
		//查询是否有父环节
		BeSectionStep parentSectionStep = beSectionStepMapper.getParentSectionStep(sectionId, stepCode);
		//父环节不为空
		if(parentSectionStep != null) {
			//根据父环节节点获取最后一个子环节节点
			BeSectionStep lastSectionStep = beSectionStepMapper.getLastSectionStep(sectionId, parentSectionStep.getStepCode());
			//判断最后一个环节是否已完成
			if(lastSectionStep != null) {
				if (beSectionExpertProgressService.getFinishStatus(lastSectionStep.getSeqId())) {
					//更新父环节完成状态
					for (BeSectionExpertProgress beSectionExpertProgress : beSectionExpertProgressMapper.selectListByStepId(parentSectionStep.getSeqId())) {
						beSectionExpertProgress.setIsFinish("1");
						beSectionExpertProgress.setUpdateTime(new Date());
						beSectionExpertProgressMapper.updateByPrimaryKey(beSectionExpertProgress);
					}
				}
			}
		}
	}

	public String getUnpassedReason(BeSectionStep beSectionStep, List<ColumnHeader> columnHeaderList,
			Map<String, Object> dataMap) {
		String enterpriseId = dataMap.get("enterprise_id") == null ? "" : dataMap.get("enterprise_id").toString();
		BeSectionEnterprise beSectionEnterprise = beSectionEnterpriseMapper.selectByPrimaryKey(enterpriseId);
		if (beSectionEnterprise != null) {
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder itemBuilder = new StringBuilder();
			for (ColumnHeader columnHeader : columnHeaderList) {
				if (ColumnType.SELECT.getCode().equals(columnHeader.getColumnType()) && "1".equals(columnHeader.getRestrictTip())) {
					if ("0".equals(dataMap.get(columnHeader.getCode()))) {
						itemBuilder.append("【" + columnHeader.getName() + "】未通过评审；<br>");
					}
				}
			}
			if(itemBuilder.length()>0) {
				stringBuilder.append("在【" + beSectionStep.getStepName() + "】中以下评审项:").append(itemBuilder);
			}
			return stringBuilder.toString();
		}
		return "";
	}

	/**
	 * 查询标段环节数据是否存在
	 * 
	 * @param sectionStepId 标段环节id
	 * @param expertId      专家id
	 * @param layoutCode    布局代码
	 * @return
	 */
	@Override
	public int selectCount(String sectionStepId, String expertId, String layoutCode) {
		return beEvalutionOutcomeMapper.selectCount(sectionStepId, expertId, layoutCode);
	}

	@Override
	public void deleteBySectionId(String sectionId) {
		beEvalutionOutcomeMapper.deleteBySectionId(sectionId);
	}
}
